<?php

namespace App\Console\Commands;

use App\Library\Lock;
use App\Library\Logic\AmountLogic;
use App\Library\Logic\InviteLogic;
use App\Library\Logic\SalesRecordLogic;
use App\Library\Logic\ShopOrderLogic;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Model;

class ShopOrderSettlementCommand extends Command
{
    /**
     * 订单商品结算
     *
     * @var string
     */
    protected $signature = 'command:shopOrderSettlement {serialNumber}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Execute the console command.
     */
    public function handle(): void
    {
        $serialNumber = $this->argument('serialNumber');
        if (empty($serialNumber) || strlen($serialNumber) !== 20) return;
        $order = ShopOrderLogic::findBySerialNumber($serialNumber);
        if (is_null($order)) return;
        Lock::get($order->serial_number . $this->signature, function () use ($order) {
            $this->handleLock($order);
        });
    }

    /**
     * handleLock
     * @param Model $order
     * @return void
     * @throws Exception
     */
    private function handleLock(Model $order): void
    {
        if ($order->ext->settlement_script === 1) return;
        else if (!is_null($order->ext->refund_cut_off_at)) return;
        else if (is_null($order->orderReturn) && is_null($order->ext->confirm_at)) return;
        else if (now()->subSeconds((int)__('base.confirmTtl'))->lt(now()->parse($order->ext->confirm_at))) return;
        else if (!is_null($order->orderReturn)) {
            if (in_array($order->orderReturn->or_buy_status, [1, 2, 4, 5])) {
                mq('shopOrderSettlement', $order->serial_number, (int)__('base.settleDelayTtl'));
                return;
            } else if ($order->orderReturn->or_buy_status === 3) {
                if ((int)$order->orderReturn->or_approved_time + (int)__('base.settleDelayTtl') < time()) {
                    mq('shopOrderSettlement', $order->serial_number, (int)__('base.settleDelayTtl'));
                    return;
                }
            }
        } else if (is_null($order->ext->deliver_at)) return;
        $order->ext->refund_cut_off_at = $order->ext->refund_at ?? now();
        $order->ext->complete_at = $order->ext->refund_cut_off_at;
        $order->ext->status_complete = 1;
        $order->ext->status_settlement = 1;
        $order->ext->settlement_at = $order->ext->refund_cut_off_at;
        $order->ext->settlement_script = 1;
        $order->ext->save();
        $this->shopOrder($order);
        $this->commission($order);
    }

    /**
     * shopOrder
     * @param Model $order
     * @return void
     */
    private function shopOrder(Model $order): void
    {
        $where = ['type' => 'order', 'objectType' => $order->getTable(), 'objectId' => $order->order_id];
        $amount = AmountLogic::findByWhere($where);
        $salesRecord = SalesRecordLogic::findByWhere($where);
        if (is_null($amount) && !is_null($salesRecord)) {
            AmountLogic::insertForModelOfLock(array_merge($where, [
                'title' => '收入(商品)',
                'userId' => $salesRecord->to_user_id,
                'amount' => $salesRecord->amount,
            ]));
            $salesRecord->status = 1;
            $salesRecord->save();
        }
    }

    /**
     * commission
     * @param Model $order
     * @return void
     */
    private function commission(Model $order): void
    {
        $where = ['type' => 'invite', 'objectType' => $order->getTable(), 'objectId' => $order->order_id];
        $amount = AmountLogic::findByWhere($where);
        $salesRecord = SalesRecordLogic::getByWhere($where);

        if (is_null($amount) && !is_null($salesRecord)) {
            foreach ($salesRecord as $item) {
                AmountLogic::insertForModelOfLock(array_merge($where, [
                    'title' => '收入(商品佣金)',
                    'userId' => $item->to_user_id,
                    'amount' => $item->amount,
                ]));

                $item->status = 1;
                $item->save();
            }
        }
    }
}
